﻿using UnityEngine;
using System.Collections;
using System;
using System.Net;
using System.Net.Sockets;
using ProtoBuf;
using System.IO;
using System.Threading;
using TcpConnector;
using com.bot.game.shuankou.msg;
using System.Collections.Generic;
//通知消息结构


/// <summary>
/// 
/// TcpConnector
///socket 连接：异步建立连接，开启独立线程异步收发数据，缓存解析数据流处理粘包，数据包交给 NetWorkMgr 处理
///NetDataHandler
///继承 MonoBehaviour 的 unity 脚本类，负责解析网络数据包的实际业务含义，分发到各逻辑模块，转发各逻辑模块的网络数据到 NetSocket
/// 
/// author zhuyu
/// pb 前后台交互
/// 读取解析2进制流
/// </summary>

public class NetDataHandler : MonoBehaviour
{
    private volatile static NetDataHandler _instance = null;

    private static readonly object lockThread = new object();//锁线程  定义一个标识确保线程同步
       
    //   private Connector conn;

    //等候通知到unity各对象的消息队列
    [HideInInspector]
    private List<TcpPckStruct> _notifys = new List<TcpPckStruct>();

    List<TcpPckStruct> _currentNotifys = new List<TcpPckStruct>();

    private float heatTime;

    public static NetDataHandler Instance
    {
        // 当第一个线程运行到这里时，此时会对locker对象 "加锁"，
        // 当第二个线程运行该方法时，首先检测到locker对象为"加锁"状态，该线程就会挂起等待第一个线程解锁
        // lock语句运行完之后（即线程运行完之后）会对该对象"解锁"
        // 双重锁定只需要一句判断就可以了
        get
        {
            if (_instance == null)
            {
                lock (lockThread)
                {
                    _instance = FindObjectOfType(typeof(NetDataHandler)) as NetDataHandler;
                    if (_instance == null)
                    {
                        _instance = new GameObject("NetDataHandler").AddComponent<NetDataHandler>();

                    }
                    // if (_instance == null)
                    //    _instance = new NetDataHandler();
                }
            }
            return _instance;
        }
        set
        {
            _instance = value;
        }
    }

    private void Awake()
    {
        Connector.instance.Connect(); //请邱伟森将此方法 放到程序进入load后端初始化界面后调用
        //脚本载入就注册方法
        Connector.instance.SocketMessageEvent += ListenProcess;

        //切换场景不释放对象，确保socket生命周期等同游戏生命周期
        DontDestroyOnLoad(this.gameObject);
        // conn = new Connector();
    }

    private void Update()
    {
        //拷贝列表尽快释放锁
        if (_notifys.Count > 0)
        {
            lock (_notifys)
            {
                _currentNotifys.Clear();
                _currentNotifys.AddRange(_notifys);
                _notifys.Clear();
            }
        }
        if (_currentNotifys.Count > 0)
        {
          /*  foreach (TcpPckStruct n in _currentNotifys)
            {
                //发送消息
            }*/
        }
    }

    public void HeatUpdate()// 心跳包？？
    {
        if (Connector.instance.client != null)
        {
            if ((Time.time - heatTime) > 10)
            {
                heatTime = Time.time;
                send(NetEvent.HEART_BEAT);
            }
        }

    }

    private void OnDestroy()
    {
        //    conn.GetInstance().Closed();
    }

    private void ListenProcess(TcpPckStruct ret)
    {
        //解析处理网络数据
        //code ...
        //插入到列表
        lock (_notifys)
        {
            TcpPckStruct ns = new TcpPckStruct();
            ns  = ret;
            Debug.Log("receive Tcp Package!" + ns.Type +" "+ ns.Size);
            _notifys.Add(ns);
        }
    }

    public void send(int sendType, byte[] data =null )// 起网络线程
    {
        try
        {
            if (!Connector.instance.client.Connected)
            {        
                Connector.instance.Connect();
            }
            if (Connector.instance.client.Connected)
            {
                Connector.instance.Write(sendType, data);

                Connector.instance.Read();//.Content;
            }
        }
        catch
        {
        }

    }

}